package IntelIpps

/*
#cgo CFLAGS: -ID:/DevelopTools/IPPS2022/ipp/2021.12/include
#cgo LDFLAGS: -LD:/DevelopTools/IPPS2022/ipp/2021.12/lib -lipps -lippcore
#include <ipp.h>
#include <stdlib.h>
*/
import "C"
import (
	"unsafe"
)

type resampleState struct {
	state   *C.IppsResamplingPolyphaseFixed_32f
	inRate  int
	outRate int
}

var resampleGlobal *resampleState

func (i *IppImpl) ResampleInit(inRate, outRate int) {
	if inRate <= 0 || outRate <= 0 {
		return
	}

	// 释放旧状态
	i.ResampleFree()

	history := 128
	var size, len, height C.int
	status := C.ippsResamplePolyphaseFixedGetSize_32f(
		C.int(inRate), C.int(outRate), C.int(2*(history-1)),
		&size, &len, &height, C.ippAlgHintFast,
	)
	if status != C.ippStsNoErr {
		return
	}

	state := (*C.IppsResamplingPolyphaseFixed_32f)(C.malloc(C.size_t(size)))
	if state == nil {
		return
	}

	status = C.ippsResamplePolyphaseFixedInit_32f(
		C.int(inRate), C.int(outRate), C.int(2*(history-1)),
		C.float(0.95), C.float(9.0), state, C.ippAlgHintFast,
	)
	if status != C.ippStsNoErr {
		C.free(unsafe.Pointer(state))
		return
	}

	resampleGlobal = &resampleState{
		state:   state,
		inRate:  inRate,
		outRate: outRate,
	}
}

func (i *IppImpl) Resample(src []float32, norm float32) ([]float32, int) {
	if resampleGlobal == nil || len(src) == 0 {
		return src, len(src)
	}

	// 估算输出长度
	outLen := int(float64(len(src)) * float64(resampleGlobal.outRate) / float64(resampleGlobal.inRate))
	if outLen == 0 {
		outLen = 1
	}
	dst := make([]float32, outLen)

	var time C.double = C.double(128) // history
	var retLen C.int

	status := C.ippsResamplePolyphaseFixed_32f(
		(*C.Ipp32f)(unsafe.Pointer(&src[0])),
		C.int(len(src)),
		(*C.Ipp32f)(unsafe.Pointer(&dst[0])),
		C.float(norm),
		&time,
		&retLen,
		resampleGlobal.state,
	)
	if status != C.ippStsNoErr {
		return src, len(src)
	}

	return dst[:retLen], int(retLen)
}

func (i *IppImpl) ResampleFree() {
	if resampleGlobal != nil && resampleGlobal.state != nil {
		C.free(unsafe.Pointer(resampleGlobal.state))
		resampleGlobal = nil
	}
}
